﻿using BetterPlaceAdmin.BetterAdminService;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Windows.Forms;

namespace BetterPlaceAdmin
{
    public partial class AdminGui : Form
    {
        private static IBetterAdminService adminService = new BetterAdminServiceClient();

        // End client global data
        private City _city = new City();

        // Begin client global data
        private Customer _customer = new Customer(); // Used to keep the selected customers data,

        // available for different tabs.

        private bool _programStart; // Indicated that this is the first time we load.
        private Reservation _resv = new Reservation(); // Route works with a temp and real
                                                       // reservation.

        public AdminGui()
        {
            try
            {
                InitializeComponent();
                StartProgressBar("Vent venligst imens alt program data hentes");
                // First time the program loads we start two backgroundworkers, this makes them wait
                // for each other to finish before reseting the status.
                _programStart = true;
                bwCustomersGetAll.RunWorkerAsync();
                bwStationGetAll.RunWorkerAsync();
                bwReservationGetAll.RunWorkerAsync();
            }
            catch (TimeoutException tie)
            {
                ShowUserFriendlyError("Timeout exception: " + tie.Message, "Timeout exception");
            }
            catch (Exception e)
            {
                ShowUserFriendlyError("Exception: " + e.Message, "Exception");
            }
        }

        private void tabControl1_SelectedIndexChanged(object sender, EventArgs e)
        {
            int index = tabControl1.SelectedIndex;
            switch (index)
            {
                case 2:
                    if (!bwReservationGetAll.IsBusy)
                    {
                        StartProgressBar("Vent venligst imens reservationer hentes");
                        btnCancelReservation.Enabled = false;

                        bwReservationGetAll.RunWorkerAsync();
                    }

                    break;

                case 4:
                    if (!bwStationGetAll.IsBusy)
                    {
                        StartProgressBar("Vent venligst imens stationslisten opdateres");
                        bwStationGetAll.RunWorkerAsync();
                    }

                    break;
            }
        }

        #region Station

        /// <summary>
        /// Create station, and call background worker
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnStationCreate_Click(object sender, EventArgs e)
        {
            try
            {
                var s = new Station
                {
                    Name = txtStationName.Text,
                    Address = txtStationAddress.Text,
                    Batteries = Convert.ToInt32(txtStationBatteries.Text),
                    City = txtStationCity.Text,
                    PostalCode = Convert.ToInt32(txtStationPostalCode.Text),
                    Latitude = Convert.ToDouble(txtStationLatitude.Text),
                    Longtitude = Convert.ToDouble(txtStationLongtitude.Text)
                };

                StartProgressBar("Vent venligst imens stationen laves.");
                adminService.CreateStation(s);
                if (!bwReservationGetAll.IsBusy)
                {
                    bwStationGetAll.RunWorkerAsync();

                    dataGVStation.Update();
                    dataGVStation.Refresh();
                }
            }
            catch (Exception ex)
            {
                ShowUserFriendlyError("En fejl opstod under forsøget på at gemme stationen " + ex.Message, "Fejl");
            }
        }

        /// <summary>
        /// Create a connection between two stations
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnStationCreateConnection_Click(object sender, EventArgs e)
        {
            try
            {
                long fromStation = Convert.ToInt32(txtStationId.Text);
                var s = (Station)cmbStationConnection.SelectedItem;
                long toStation = s.Id;
                double distance = Convert.ToDouble(txtStationConnectionDist.Text);
                TimeSpan time = TimeSpan.FromMinutes(Convert.ToDouble(txtStationConnectionTime.Text));
                var edge = new Edge
                {
                    FirstNode = new Node
                    {
                        Station = new Station { Id = fromStation }
                    },
                    SecondNode = new Node
                    {
                        Station = new Station { Id = toStation }
                    },
                    Distance = distance,
                    Time = time
                };
                // Edge edge = new Edge(fromStation, toStation, distance, time);
                StartProgressBar("Vent venligst imens forbindelsen imellem stationerne gemmes.");
                adminService.CreateEdge(edge);

                if (!bwStationGetAllConnections.IsBusy)
                {
                    bwStationGetAllConnections.RunWorkerAsync();
                }

                ClearConnection();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        /// <summary>
        /// Delete the shown station id.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnStationDelete_Click(object sender, EventArgs e)
        {
            DialogResult r = MessageBox.Show(@"Er du sikker på du vil slette den valgte station?",
                @"Slet station?", MessageBoxButtons.OKCancel,
                MessageBoxIcon.Question,
                MessageBoxDefaultButton.Button1,
                0, false);

            if (r.Equals(DialogResult.OK))
            {
                try
                {
                    adminService.DeleteStation(Convert.ToInt64(txtStationId.Text));
                    StartProgressBar("Vent venligst imens stationen slettes.");
                    if (!bwStationGetAll.IsBusy)
                    {
                        bwStationGetAll.RunWorkerAsync();

                        dataGVStation.Update();
                        dataGVStation.Refresh();
                    }
                }
                catch (Exception ex)
                {
                    ShowUserFriendlyError("En fejl opstod under forsøget på at slette stationen " + ex.Message, "Fejl");
                }
            }
        }

        /// <summary>
        /// Delete connection between two stations
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnStationDeleteConnection_Click(object sender, EventArgs e)
        {
            if (dataGVStationConnections.SelectedRows.Count > 0)
            {
                DialogResult r = MessageBox.Show(@"Er du sikker på du vil slette den valgte forbindelse?",
                    @"Slet station?", MessageBoxButtons.OKCancel,
                    MessageBoxIcon.Question,
                    MessageBoxDefaultButton.Button1,
                    0, false);

                if (r.Equals(DialogResult.OK))
                {
                    try
                    {
                        Edge edge = dataGVStationConnections.SelectedRows[0].DataBoundItem as Edge;
                        if (edge != null)
                        {
                            long fromStation = edge.FirstNode.Station.Id;
                            long toStation = edge.SecondNode.Station.Id;
                            var intData = adminService.DeleteEdge(fromStation, toStation);
                            if (intData.SerStatus.Equals("Ok"))
                            {
                                int rc = intData.SerData;
                                if (rc == -1)
                                {
                                    throw new Exception("Error: Edge not deleted!");
                                }
                            }
                            else
                            {
                                ShowUserFriendlyError(intData.SerErrorDescription, intData.SerStatus);
                            }
                        }
                        StartProgressBar("Vent venligst imens forbindelsen imellem stationerne slettes.");
                        if (!bwStationGetAllConnections.IsBusy)
                        {
                            bwStationGetAllConnections.RunWorkerAsync();
                        }
                    }
                    catch (Exception ex)
                    {
                        ShowUserFriendlyError("En fejl opstod under forsøget på at slette forbindelsen " + ex.Message, "Fejl");
                    }
                }
            }
        }

        /// <summary>
        /// Update the station with the shown Id
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnStationUpdate_Click(object sender, EventArgs e)
        {
            try
            {
                Station s = new Station
                {
                    Id = Convert.ToInt64(txtStationId.Text),
                    Name = txtStationName.Text,
                    Address = txtStationAddress.Text,
                    Batteries = Convert.ToInt32(txtStationBatteries.Text),
                    City = txtStationCity.Text,
                    PostalCode = Convert.ToInt32(txtStationPostalCode.Text),
                    Latitude = Convert.ToDouble(txtStationLatitude.Text),
                    Longtitude = Convert.ToDouble(txtStationLongtitude.Text)
                };
                StartProgressBar("Vent venligst imens stationen opdateres.");
                adminService.UpdateStation(s);
                if (!bwStationGetAll.IsBusy)
                {
                    bwStationGetAll.RunWorkerAsync();

                    dataGVStation.Update();
                    dataGVStation.Refresh();
                }
            }
            catch (Exception ex)
            {
                ShowUserFriendlyError("En fejl opstod under forsøget på at opdatere stationen " + ex.Message, "Fejl");
            }
        }

        private void ClearConnection()
        {
            txtStationConnectionName.Text = txtStationName.Text;
            cmbStationConnection.SelectedIndex = -1;
            txtStationConnectionDist.Text = "";
            txtStationConnectionTime.Text = "";
        }

        private void ClearStation()
        {
            txtStationName.Text = "";
            txtStationAddress.Text = "";
            txtStationPostalCode.Text = "";
            txtStationCity.Text = "";
            txtStationBatteries.Text = "";
            txtStationLongtitude.Text = "";
            txtStationLatitude.Text = "";
        }

        private void dataGVStation_SelectionChanged(object sender, EventArgs e)
        {
            GetStationValues();
            if (dataGVStation.CurrentRow != null)
            {
                var s = dataGVStation.CurrentRow.DataBoundItem as Station;
                dataGVStation.Enabled = false;
                object genericObject = s;
                StartProgressBar("Vent venligst imens stationens forbindelser hentes");
                if (!bwStationGetAllConnections.IsBusy)
                {
                    bwStationGetAllConnections.RunWorkerAsync(genericObject);
                }
            }
            ClearConnection();
        }

        private void GetStationValues()
        {
            if (dataGVStation.SelectedRows.Count > -1)
            {
                try
                {
                    if (dataGVStation.CurrentRow != null)
                    {
                        var s = dataGVStation.CurrentRow.DataBoundItem as Station;

                        if (s != null)
                        {
                            txtStationId.Text = s.Id.ToString(CultureInfo.InvariantCulture);
                            txtStationName.Text = s.Name;
                            txtStationAddress.Text = s.Address;
                            txtStationPostalCode.Text = s.PostalCode.ToString(CultureInfo.InvariantCulture);
                            txtStationCity.Text = s.City;
                            txtStationBatteries.Text = s.Batteries.ToString(CultureInfo.InvariantCulture);
                            txtStationLongtitude.Text = s.Longtitude.ToString(CultureInfo.InvariantCulture);
                            txtStationLatitude.Text = s.Latitude.ToString(CultureInfo.InvariantCulture);
                        }
                    }
                }
                catch (Exception)
                {
                    ClearStation();
                }
            }
        }

        /// <summary>
        /// This is called as the user is typing the postal code.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void txtStationPostalCode_KeyPress(object sender, KeyPressEventArgs e)
        {
            StartProgressBar("Vent venligst imens en by findes for det indtastede post nummer.");
            bwAdminGuiZipToCity.RunWorkerAsync();
        }

        #region BackgroundWorker Station

        private void bwStationsGetAll_DoWork(object sender, DoWorkEventArgs e)
        {
            e.Result = adminService.GetAllStations();
        }

        /// <summary>
        /// Once all stations have been fetched from the db, populate the FromStation Dropdown.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void bwStationsGetAll_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            //Receive the result from DoWork and set dataGVStation.Datasource
            var stationList = e.Result as StationList;
            if (stationList != null && stationList.SerStatus.Equals("Ok"))
            {
                dataGVStation.DataSource = (new List<Station>(stationList.SerData));
                if ((dataGVStation.DataSource as List<Station>).Any())
                {
                    cmbRouteFromStation.Items.Clear();
                    foreach (var s in (dataGVStation.DataSource as List<Station>))
                    {
                        cmbRouteFromStation.Items.Add(s);
                    }
                    cmbRouteFromStation.Enabled = true;
                }
            }
            else
            {
                if (stationList != null)
                {
                    ShowUserFriendlyError(stationList.SerErrorDescription, stationList.SerStatus);
                }
            }
            ResetProgressBar();
        }

        #endregion BackgroundWorker Station

        #region BackgroundWorker Edges

        private void bwStationsGetAllConnections_DoWork(object sender, DoWorkEventArgs e)
        {
            if (dataGVStation.CurrentRow != null && dataGVStation.SelectedRows.Count > 0)
            {
                var s = dataGVStation.SelectedRows[0].DataBoundItem as Station;
                if (s != null)
                {
                    e.Result = adminService.GetStationEdges(s.Id);
                }
            }
        }

        private void bwStationsGetAllConnections_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            dataGVStation.Enabled = true;
            if (dataGVStation.SelectedRows.Count > -1)
            {
                var s = dataGVStation.SelectedRows[0].DataBoundItem as Station;
                if (s != null)
                {
                    long id = s.Id;
                    // Handle the data.
                    var edgeList = e.Result as EdgeList;
                    if (edgeList != null && edgeList.SerStatus.Equals("Ok"))
                    {
                        if (dataGVStation.CurrentRow != null)
                        {
                            var edgeListSorted = SortEdges(new List<Edge>(edgeList.SerData), id);
                            edgeBindingSource.DataSource = edgeListSorted;
                        }
                    }
                    else
                    {
                        if (edgeList != null) ShowUserFriendlyError(edgeList.SerErrorDescription, edgeList.SerStatus);
                    }
                    //Receive the result from DoWork and set dataGVStationConnections.Datasource
                    dataGVStationConnections.ClearSelection();

                    //Set the combobox's list items to only the possible connection cities
                    cmbStationConnection.DataSource = GetPossibleConnections(id);
                }

                //clear selection in the combobox
                cmbStationConnection.SelectedIndex = -1;
                ResetProgressBar();
            }
        }

        private List<Station> GetPossibleConnections(long stationId)
        {
            var possibleConList = new List<Station>();

            // Station station = dataGVStation.CurrentRow.DataBoundItem as Station;
            long id = stationId;

            //Copies all  stations to the possibleConList
            var allStations = dataGVStation.DataSource as List<Station>;
            if (allStations != null)
            {
                foreach (Station station in allStations)
                {
                    possibleConList.Add(station);
                }
            }

            //A list is created for the stations, that are already connected to the selected station
            var currentConnections = new List<Station>();
            var edges = edgeBindingSource.DataSource as List<Edge>;
            if (edges != null)
            {
                foreach (Edge edge in edges)
                {
                    currentConnections.Add(edge.SecondNode.Station);
                }
            }

            //delegate that removes the selected station from possibleConList
            possibleConList.RemoveAll(s => s.Id == id);

            //delegate that removes stations from possibleConList, if they are already made connections to
            possibleConList.RemoveAll(s => currentConnections.Any(s2 => s2.Id == s.Id));

            return possibleConList;
        }

        private List<Edge> SortEdges(List<Edge> edgeList, long id)
        {
            foreach (var edge in edgeList)
            {
                if (edge.FirstNode.Station.Id != id)
                {
                    var tempStation = edge.FirstNode.Station;
                    edge.FirstNode.Station = edge.SecondNode.Station;
                    edge.SecondNode.Station = tempStation;
                }
            }
            return edgeList;
        }

        #endregion BackgroundWorker Edges

        #region BackgroundWorker City

        private void bwAdminGuiZipToCity_DoWork(object sender, DoWorkEventArgs e)
        {
            if (txtStationPostalCode.Text.Length == 4)
            {
                int number;
                bool result = Int32.TryParse(txtStationPostalCode.Text, out number);
                if (result)
                {
                    int postalCode = Convert.ToInt32(txtStationPostalCode.Text);
                    e.Result = adminService.GetCityFromPostalCode(postalCode);
                }
            }
        }

        private void bwAdminGuiZipToCity_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            var cityData = e.Result as CityData;
            if (cityData != null && cityData.SerStatus.Equals("Ok"))
            {
                _city = cityData.SerData;
                txtStationCity.Text = _city != null ? _city.CityName : "By ikke fundet!";
            }
            else
            {
                if (cityData != null) ShowUserFriendlyError(cityData.SerErrorDescription, cityData.SerStatus);
            }
            ResetProgressBar();
        }

        #endregion BackgroundWorker City

        #endregion Station

        #region Customer

        /// <summary>
        /// Create new customer.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnCustCreate_Click(object sender, EventArgs e)
        {
            try
            {
                var c = new Customer
                {
                    Name = txtCustName.Text,
                    Address = txtCustAddress.Text,
                    PostalCode = Convert.ToInt16(txtCustZip.Text),
                    City = txtCustCity.Text,
                    PhoneNo = Convert.ToInt64(txtCustPhone.Text),
                    Email = txtCustEmail.Text,
                    BillingInfo = txtCustBillingInfo.Text
                };
                StartProgressBar("Vent venligst imens kunden bliver oprettet.");
                adminService.CreateCustomer(c);
                if (!bwCustomersGetAll.IsBusy)
                {
                    bwCustomersGetAll.RunWorkerAsync();

                    dataCustomerlist.Update();
                    dataCustomerlist.Refresh();
                }
            }
            catch (Exception ex)
            {
                ShowUserFriendlyError("En fejl opstod under forsøget på at gemme kunden " + ex.Message, "Fejl");
            }
        }

        /// <summary>
        /// Delete the currently selected customer, shown Id
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnCustDelete_Click(object sender, EventArgs e)
        {
            DialogResult r = MessageBox.Show(@"Er du sikker på du vil slette den valgte kunde?",
                @"Slet kunde?", MessageBoxButtons.OKCancel,
                MessageBoxIcon.Question,
                MessageBoxDefaultButton.Button1,
                0, false);

            if (r.Equals(DialogResult.OK))
            {
                try
                {
                    StartProgressBar("Vent venligst imens kunden bliver slettet.");
                    adminService.DeleteCustomer(Convert.ToInt16(txtCustId.Text));
                    if (!bwCustomersGetAll.IsBusy)
                    {
                        bwCustomersGetAll.RunWorkerAsync();

                        dataCustomerlist.Update();
                        dataCustomerlist.Refresh();
                    }
                }
                catch (Exception ex)
                {
                    ShowUserFriendlyError("En fejl opstod under forsøget på at opdatere kunden " + ex.Message, "Opdaterings fejl");
                }
            }
        }

        /// <summary>
        /// Customer update.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnCustUpdate_Click(object sender, EventArgs e)
        {
            try
            {
                Customer c = new Customer
                {
                    Id = Convert.ToInt64(txtCustId.Text),
                    Name = txtCustName.Text,
                    Address = txtCustAddress.Text,
                    PostalCode = Convert.ToInt16(txtCustZip.Text),
                    City = txtCustCity.Text,
                    PhoneNo = Convert.ToInt64(txtCustPhone.Text),
                    Email = txtCustEmail.Text,
                    BillingInfo = txtCustBillingInfo.Text
                };
                StartProgressBar("Vent venligst imens kundens data bliver opdateret.");
                adminService.UpdateCustomer(c);
                if (!bwCustomersGetAll.IsBusy)
                {
                    bwCustomersGetAll.RunWorkerAsync();

                    dataCustomerlist.Update();
                    dataCustomerlist.Refresh();
                }
            }
            catch (Exception ex)
            {
                ShowUserFriendlyError("En fejl opstod under forsøget på at opdatere kunden " + ex.Message, "Opdaterings fejl");
            }
        }

        private void ClearCustomer()
        {
            txtCustName.Text = "";
            txtCustAddress.Text = "";
            txtCustCity.Text = "";
            txtCustZip.Text = "";
            txtCustEmail.Text = "";
            txtCustPhone.Text = "";
            txtCustBillingInfo.Text = "";
        }

        private void GetCustomerValues()
        {
            if (dataCustomerlist.SelectedRows.Count > -1)
            {
                try
                {
                    var c = dataCustomerlist.SelectedRows[0].DataBoundItem as Customer;

                    if (c != null)
                    {
                        txtCustId.Text = c.Id.ToString(CultureInfo.InvariantCulture);
                        txtCustName.Text = c.Name;
                        txtCustAddress.Text = c.Address;
                        txtCustZip.Text = c.PostalCode.ToString(CultureInfo.InvariantCulture);
                        txtCustCity.Text = c.City;
                        txtCustPhone.Text = c.PhoneNo.ToString(CultureInfo.InvariantCulture);
                        txtCustEmail.Text = c.Email;
                        txtCustBillingInfo.Text = c.BillingInfo;
                    }
                }
                catch (Exception)
                {
                    ClearCustomer();
                }
            }
        }

        #region BackgroundWorker Customer

        private void bwCustomersGetAll_DoWork(object sender, DoWorkEventArgs e)
        {
            e.Result = adminService.GetAllCustomers();
        }

        /// <summary>
        /// Gets all customers, and populates the Dropdown list on "Rute" tab.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void bwCustomersGetAll_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            //Receive the result from DoWork and set dataCustCustomerList.Datasource
            PersonList personList = e.Result as PersonList;
            if (personList != null && personList.SerStatus.Equals("Ok"))
            {
                customerBindingSource.DataSource = new List<Customer>(personList.SerData);
                dataCustomerlist.Update();
                dataCustomerlist.Refresh();

                if ((customerBindingSource.DataSource as List<Customer>).Any())
                {
                    cmbRouteCustomer.Items.Clear();
                    foreach (var c in (customerBindingSource.DataSource as List<Customer>))
                    {
                        cmbRouteCustomer.Items.Add(c.Name);
                    }
                    cmbRouteCustomer.Enabled = true;
                }
            }
            else
            {
                if (personList != null) ShowUserFriendlyError(personList.SerErrorDescription, personList.SerStatus);
            }

            ResetProgressBar();
        }

        #endregion BackgroundWorker Customer

        #endregion Customer

        #region Route

        /// <summary>
        /// Cancel/Deny the displayed route, calls the clientService to release batteries.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnClearRoute_Click(object sender, EventArgs e)
        {
            StartProgressBar("Vent venligst imens din rute annulleres.");
            adminService.CancelReservation(_resv.Id);
            _resv = new Reservation();
            routeBindingSource.Clear();
            if (!bwReservationGetAll.IsBusy)
            {
                bwReservationGetAll.RunWorkerAsync();
            }
            cmbRouteFromStation.Enabled = true;
            cmbRouteToStation.Enabled = false;
        }

        /// <summary>
        /// Accept the currently displayed route.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnCommitRoute_Click(object sender, EventArgs e)
        {
            btnCommitRoute.Enabled = false;
            StartProgressBar("Vent venligst imens din reservation gemmes.");
            _resv.Status = ReservationsStatus.Accepted;
            bwRouteCreateReservation.RunWorkerAsync();
            if (!bwReservationGetAll.IsBusy)
            {
                bwReservationGetAll.RunWorkerAsync();
            }
            tabControl1.SelectTab(2);
            cmbRouteFromStation.Enabled = true;
            cmbRouteToStation.Enabled = false;
        }

        private void btnFindRoute_Click(object sender, EventArgs e)
        {
            if (cmbRouteFromStation.SelectedIndex > -1 && cmbRouteToStation.SelectedIndex > -1 &&
                cmbRouteCustomer.SelectedIndex > -1)
            {
                StartProgressBar("Vent venligst imens din rute findes.");
                btnCommitRoute.Enabled = false;

                _resv = new Reservation
                {
                    Route = new Route(),
                    Customer = GetCustomerByName(cmbRouteCustomer.SelectedItem.ToString())
                };
                _resv.Route.StartStation = GetStationByName(cmbRouteFromStation.SelectedItem.ToString());
                _resv.Route.EndStation = GetStationByName(cmbRouteToStation.SelectedItem.ToString());
                _resv.Date = dateTimeRoute.Value;
                if (!bwRouteGetGenerated.IsBusy)
                {
                    bwRouteGetGenerated.RunWorkerAsync();
                }
            }
        }

        private void cmbRouteCustomer_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (cmbRouteCustomer.SelectedIndex > -1)
            {
                _customer = GetCustomerByName(cmbRouteCustomer.SelectedItem.ToString());
                _resv = GetUnFinishedReservations(_customer.Id);
                //routeBindingSource.DataSource = _resv.Route;
                if (_resv != null)
                {
                    routeBindingSource.DataSource = _resv.Route;
                }
                else
                {
                    routeBindingSource.DataSource = new Route();
                }
            }
        }

        /// <summary>
        /// When we select an an station, remove it from the other dropdown list. Making sure that a
        /// route will not be to it self.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void cmbRouteFromStation_SelectedIndexChanged(object sender, EventArgs e)
        {
            cmbRouteToStation.Items.Clear();
            foreach (var item in cmbRouteFromStation.Items)
            {
                if (cmbRouteFromStation.SelectedItem != item)
                {
                    cmbRouteToStation.Items.Add(item);
                }
            }
            cmbRouteToStation.Enabled = true;
        }

        /// <summary>
        /// When we have the customers name, we want the object returned.
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        private Customer GetCustomerByName(string name)
        {
            return (from c in (customerBindingSource.DataSource as List<Customer>)
                    where c.Name == name
                    select c).FirstOrDefault();
        }

        /// <summary>
        /// We got the stations name, this returns the first matching station object.
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        private Station GetStationByName(string name)
        {
            return (from s in (dataGVStation.DataSource as List<Station>)
                    where s.Name == name
                    select s).FirstOrDefault();
        }

        /// <summary>
        /// If a customer has non accepted rutes, this means that the booking was interrupted This
        /// returns the reservation so the work can continue.
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        private Reservation GetUnFinishedReservations(long id)
        {
            List<Reservation> resvList = (reservationsBindingSource.DataSource as List<Reservation>);
            Reservation reservation;
            if (resvList != null)
            {
                reservation = (from r in resvList
                               where r.Customer.Id == id && r.Status == ReservationsStatus.Created
                               select r).FirstOrDefault();
            }
            else
            {
                reservation = new Reservation();
                reservation.Route = new Route();
            }
            return reservation;
        }

        #region BackgroundWorkers for route

        /// <summary>
        /// User accepted the proposed route.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void bwRouteCreateReservation_DoWork(object sender, DoWorkEventArgs e)
        {
            _resv.Status = ReservationsStatus.Accepted;
            e.Result = adminService.UpdateReservation(_resv);
        }

        private void bwRouteCreateReservation_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            var intData = (IntData)e.Result;
            if (intData.SerStatus.Equals("Ok"))
            {
                _resv = new Reservation();
                _resv.Route = new Route();

                routeBindingSource.DataSource = _resv.Route;
            }
            else
            {
                ShowUserFriendlyError(intData.SerErrorDescription, intData.SerStatus);
            }
            ResetProgressBar();
            btnCommitRoute.Enabled = true;
        }

        /// <summary>
        /// Get the route generated by the algorithm.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void bwRouteGetGenerated_DoWork(object sender, DoWorkEventArgs e)
        {
            e.Result = adminService.CreateReservationUsingAStar(_resv.Route.StartStation.Id, _resv.Route.EndStation.Id, _resv.Customer.Id, _resv.Date);
        }

        private void bwRouteGetGenerated_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            var resvData = e.Result as ReservationData;
            if (resvData != null && resvData.SerStatus.Equals("Ok"))
            {
                _resv = resvData.SerData;
                routeBindingSource.DataSource = _resv.Route;
            }
            else
            {
                if (resvData != null) ShowUserFriendlyError(resvData.SerErrorDescription, resvData.SerStatus);
            }
            ResetProgressBar();
            btnCommitRoute.Enabled = true;
        }

        #endregion BackgroundWorkers for route

        #endregion Route

        #region Reservation

        #region BackgroundWorker Reservation

        private void bwReservationsGetAll_DoWork(object sender, DoWorkEventArgs e)
        {
            e.Result = adminService.GetAllReservations();
        }

        private void bwReservationsGetAll_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            var reservationData = e.Result as ReservationList;
            if (reservationData != null && reservationData.SerStatus.Equals("Ok"))
            {
                //Receive the result from DoWork and set dataCustCustomerList.Datasource
                reservationsBindingSource.DataSource = new List<Reservation>(reservationData.SerData);
            }
            btnCancelReservation.Enabled = true;
            ResetProgressBar();
        }

        #endregion BackgroundWorker Reservation

        /// <summary>
        /// Cancel/Deny the displayed route, calls the clientService to release batteries.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnCancelReservation_Click(object sender, EventArgs e)
        {
            btnCancelReservation.Enabled = false;
            if (dataGVReservations.SelectedRows.Count > -1 && dataGVReservations.CurrentRow != null)
            {
                var r = dataGVReservations.CurrentRow.DataBoundItem as Reservation;
                if (r != null)
                {
                    adminService.CancelReservation(r.Id);
                }
            }
            bwReservationGetAll.RunWorkerAsync();
        }

        private void dataCustomerlist_SelectionChanged(object sender, EventArgs e)
        {
            GetCustomerValues();
        }

        #endregion Reservation

        private void dataGVReservations_SelectionChanged(object sender, EventArgs e)
        {
            if (dataGVReservations.SelectedRows.Count > 0)
            {
                var reservation = dataGVReservations.SelectedRows[0].DataBoundItem as Reservation;

                if (reservation != null) partReservationsBindingSource.DataSource = reservation.PartReservations;
            }
        }

        /// <summary>
        /// We are no longer loading anything, stop the load bar and tell the user.
        /// </summary>
        private void ResetProgressBar()
        {
            if (!bwCustomersGetAll.IsBusy && !bwStationGetAll.IsBusy &&
            !bwReservationGetAll.IsBusy)
            {
                _programStart = false;
            }
            toolStripProgressBar.Visible = false;
            toolStripStatus.Text = @"Klar til brug.";
        }

        /// <summary>
        /// Show a unified error, this is used to keep the code reuse to a minimum.
        /// </summary>
        /// <param name="serErrorDescription">The error description</param>
        /// <param name="serStatus">The status was not "Ok", show it as the title.</param>
        private void ShowUserFriendlyError(string serErrorDescription, string serStatus)
        {
            MessageBox.Show(serErrorDescription, serStatus, MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
        }

        /// <summary>
        /// Show the statusbar, and print a message to show what is loading.
        /// </summary>
        /// <param name="progressDescription"></param>
        private void StartProgressBar(string progressDescription)
        {
            toolStripProgressBar.Visible = true;
            toolStripStatus.Text = progressDescription;
        }
    }
}

namespace BetterPlaceAdmin.BetterAdminService
{
    public partial class Customer
    {
        public override string ToString()
        {
            return Name;
        }
    }

    public partial class Node
    {
        public override string ToString()
        {
            return Station.ToString();
        }
    }

    public partial class Route
    {
        public override string ToString()
        {
            return StartStation + " til " + EndStation;
        }
    }

    public partial class Station
    {
        public override string ToString()
        {
            return Name;
        }
    }
}